package com.don.beetl.ext.fn;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer;

/**
 * 调试信息打印工具类
 * 
 * @author don
 * @date 2014-10-31
 * 
 */
public class DevelInfo {
	private SerializeConfig mapping = null;

	public DevelInfo() {
		if (mapping == null) {
			mapping = new SerializeConfig();
			mapping.put(Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss"));
		}
	}

	private SerializerFeature[] getFeatures() {
		// DisableCircularReferenceDetect来禁止循环引用检测
		SerializerFeature[] features = { SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.SortField,
				SerializerFeature.BrowserCompatible };
		return features;
	}

	/**
	 * 打印json数组
	 * 
	 * @return
	 */
	public String printJsonArray(List array) {
		SerializeConfig mapping = new SerializeConfig();
		mapping.put(Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss"));

		StringBuffer develinfo = new StringBuffer();// 调试信息
		develinfo.append("<div class=\"krumo-root\" dir=\"ltr\">");
		develinfo.append("<ul class=\"krumo-node krumo-first\">");
		for (Iterator iterator = array.iterator(); iterator.hasNext();) {
			Object object = (Object) iterator.next();
			String json = JSON.toJSONString(object, mapping, getFeatures());// java对象转成Json字符串
			develinfo.append(print_vars(JSONObject.parseArray(json)));
		}
		develinfo
				.append("<li class=\"krumo-footnote\"><div class=\"krumo-version\" style=\"white-space:nowrap;\"><h6>Krumo version 0.2.1a</h6> | <a href=\"http://krumo.sourceforge.net\" target=\"_blank\">http://krumo.sourceforge.net</a></div>&nbsp;</li>");
		develinfo.append("</ul>");
		develinfo.append("</div>");
		return develinfo.toString();
	}

	/**
	 * 打印json对象
	 * 
	 * @return
	 */
	public String printJsonObject(Map<String, Object> object) {
		StringBuffer develinfo = new StringBuffer();// 调试信息
		develinfo.append("<div class=\"krumo-root\" dir=\"ltr\">");
		develinfo.append("<ul class=\"krumo-node krumo-first\">");

		// 通过ArrayList构造函数把map.entrySet()转换成list
		List<Map.Entry<String, Object>> mappingList = new ArrayList<Map.Entry<String, Object>>(object.entrySet());
		// 通过比较器实现比较排序
		Collections.sort(mappingList, new Comparator<Map.Entry<String, Object>>() {
			public int compare(Map.Entry<String, Object> mapping1, Map.Entry<String, Object> mapping2) {
				return mapping1.getKey().compareTo(mapping2.getKey());// 升序
			}
		});
		for (Map.Entry<String, Object> m : mappingList) {
			Map s = new HashMap();
			s.put(m.getKey(), m.getValue());
			String json = JSON.toJSONString(s, mapping, getFeatures());// java对象转成Json字符串
			develinfo.append(print_vars(JSONObject.parseObject(json)));
		}
		develinfo
				.append("<li class=\"krumo-footnote\"><div class=\"krumo-version\" style=\"white-space:nowrap;\"><h6>Krumo version 0.2.1a</h6> | <a href=\"http://krumo.sourceforge.net\" target=\"_blank\">http://krumo.sourceforge.net</a></div>&nbsp;</li>");
		develinfo.append("</ul>");
		develinfo.append("</div>");
		return develinfo.toString();
	}

	/**
	 * 移除fastjson不支持转化的全局变量，同时也会更好看到实际模版所使用的变量
	 */
	public void removeNoSupportVar(Map vars) {
		// 去除一些SpringMVC引入的变量,同时防止Java对象转成Json字符串异常问题
		vars.remove("springMacroRequestContext");
		vars.remove("request");
		vars.remove("response");
		vars.remove("servlet");
		List<String> dmaps = new ArrayList();
		for (Iterator iterator = vars.keySet().iterator(); iterator.hasNext();) {
			String key = (String) iterator.next();
			if (key.contains(".")) {
				dmaps.add(key);
			}
		}
		for (String string : dmaps) {
			vars.remove(string);
		}
	}

	/**
	 * 遍历循环打印调试变量
	 * 
	 * @param data
	 * @return
	 */
	private String print_vars(Object clone) {
		StringBuffer develinfo = new StringBuffer();
		if (clone instanceof JSONObject) {
			JSONObject obj = (JSONObject) clone;
			develinfo.append(print_jsonobject(obj));
		} else if (clone instanceof JSONArray) {
			JSONArray jsonarr = (JSONArray) clone;
			develinfo.append(print_jsonarray(jsonarr));
		} else if (clone instanceof Object) {
			develinfo.append(print_string(clone));
		}
		return develinfo.toString();
	}

	/**
	 * 打印JSON数组
	 * 
	 * @param obj
	 * @return
	 */
	private String print_jsonarray(JSONArray clone) {
		StringBuffer develinfo = new StringBuffer();
		for (int i = 0; i < clone.size(); i++) {
			Object obj = clone.get(i);
			if (obj instanceof JSONObject) {
				JSONObject obj_ = (JSONObject) obj;
				develinfo.append(print_jsonobject2(obj_, i));
			} else if (obj instanceof JSONArray) {
				JSONArray arr_ = (JSONArray) obj;
				develinfo.append(print_jsonarray(arr_));
			} else if (null == obj) {
				develinfo.append(print_string(obj));
			} else if (obj instanceof Object) {
				develinfo.append(print_string(obj));
			}
		}
		return develinfo.toString();
	}

	/**
	 * 返回对象的个数
	 * 
	 * @param data
	 *            对象
	 * @param key
	 *            下标值
	 * @return
	 */
	private int get_child_count(Object clone, String key) {
		if (clone instanceof JSONObject) {
			JSONObject obj = (JSONObject) clone;
			Object child = obj.get(key);
			if (child instanceof JSONObject) {
				return ((JSONObject) child).size();
			} else if (child instanceof JSONArray) {
				return ((JSONArray) child).size();
			}
		} else if (clone instanceof JSONArray) {
			JSONArray obj = (JSONArray) clone;
			return obj.size();
		}
		return 0;
	}

	/**
	 * 打印JSON对象
	 * 
	 * @param obj
	 * @param index
	 * @return
	 */
	private String print_jsonobject(JSONObject clone) {
		StringBuffer develinfo = new StringBuffer();
		for (Iterator iterator = clone.keySet().iterator(); iterator.hasNext();) {
			String key = (String) iterator.next();
			Object value = clone.get(key);
			int childcount = get_child_count(clone, key);

			develinfo.append("<li class=\"krumo-child\">");
			develinfo.append("<div class=\"krumo-element" + (childcount > 0 ? " krumo-expand" : "") + "\"");
			if (childcount > 0)
				develinfo.append(" onClick=\"krumo.toggle(this);\"");
			develinfo.append(" onMouseOver=\"krumo.over(this);\"");
			develinfo.append(" onMouseOut=\"krumo.out(this);\">");

			develinfo.append("<a class=\"krumo-name\">" + key + "</a>");
			if (value instanceof JSONObject || value instanceof JSONArray) {
				develinfo.append(" (<em class=\"krumo-type\">Array, <strong class=\"krumo-array-length\"> ");
				develinfo.append("" + childcount + " elements");
				develinfo.append("</strong></em>) ");
			} else {
				if (value != null)
					develinfo.append(" (<em class=\"krumo-type\">" + (value == null ? "" : value.getClass().toString())
							+ "</em>) ");
				else
					develinfo.append(" (<em class=\"krumo-type\">" + value + "</em>) ");
			}
			if (childcount == 0)
				develinfo.append("<strong class=\"krumo-string\" >" + value + "</strong>	");

			develinfo.append("</div>");

			if (childcount > 0) {
				develinfo.append("<div class=\"krumo-nest\" style=\"display:none;\">");
				develinfo.append("<ul class=\"krumo-node\">");
				develinfo.append(print_vars(value));
				develinfo.append("</ul>");
				develinfo.append("</div>");
			}
			develinfo.append("</li>");
		}
		return develinfo.toString();
	}

	/**
	 * 打印JSON对象数组指定对象
	 * 
	 * @param obj
	 * @param index
	 * @return
	 */
	private String print_jsonobject2(JSONObject clone, int index) {
		StringBuffer develinfo = new StringBuffer();
		develinfo.append("<li class=\"krumo-child\">");
		develinfo.append("<div class=\"krumo-element krumo-expand\"");
		develinfo.append(" onClick=\"krumo.toggle(this);\"");
		develinfo.append(" onMouseOver=\"krumo.over(this);\"");
		develinfo.append(" onMouseOut=\"krumo.out(this);\">");

		develinfo.append("<a class=\"krumo-name\">[" + index + "]</a>");
		develinfo.append("(<em class=\"krumo-type\">Array, <strong class=\"krumo-array-length\"> ");
		develinfo.append("" + clone.size() + " elements");
		develinfo.append("</strong></em>) ");
		develinfo.append("</div>");

		develinfo.append("<div class=\"krumo-nest\" style=\"display:none;\">");
		develinfo.append("<ul class=\"krumo-node\">");
		develinfo.append(print_vars(clone));
		develinfo.append("</ul>");
		develinfo.append("</div>");
		develinfo.append("</li>");
		return develinfo.toString();
	}

	/**
	 * 打印字符或对象
	 * 
	 * @param obj
	 * @param index
	 * @return
	 */
	private String print_string(Object clone) {
		StringBuffer develinfo = new StringBuffer();

		develinfo.append("<li class=\"krumo-child\">");
		develinfo.append("<div class=\"krumo-element");
		develinfo.append(" onMouseOver=\"krumo.over(this);\"");
		develinfo.append(" onMouseOut=\"krumo.out(this);\">");

		develinfo.append("<a class=\"krumo-name\" >" + clone + "</a>");
		develinfo.append(" (<em class=\"krumo-type\">" + (clone == null ? "" : clone.getClass().toString()) + "</em>) ");
		develinfo.append("</div>");
		develinfo.append("</li>");
		return develinfo.toString();
	}
}